package br.org.acessobrasil.portal.action;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;

import br.org.acessobrasil.portal.modelo.ItemBusca;
import br.org.acessobrasil.portal.modelo.LogBusca;
import br.org.acessobrasil.portal.modelo.Pagina;
import br.org.acessobrasil.portal.modelo.PalavraChave;
import br.org.acessobrasil.portal.modelo.RelatorioBusca;
import br.org.acessobrasil.portal.persistencia.BuscaDaoSpring;
import br.org.acessobrasil.portal.persistencia.ItemConteudoDaoSpring;
import br.org.acessobrasil.portal.persistencia.LogBuscaDao;
import br.org.acessobrasil.portal.persistencia.PaginaDaoSpring;
import br.org.acessobrasil.portal.util.ListItem;

import com.opensymphony.xwork2.ActionSupport;
/**
 * Trata a busca no administrativo e a do internauta
 * @author Renato Nati, Fabio Issamu Oshiro
 *
 */
public class BuscaAction extends ActionSupport {
	private static final long serialVersionUID = -3372043037114745429L;
	private static Logger logger = Logger.getLogger(BuscaAction.class);
	private ArrayList<ItemBusca> itensBusca = new ArrayList<ItemBusca>();
	private String texto = new String();
	private String txtBusca = new String();
	private List<ItemBusca> resultados = new ArrayList<ItemBusca>();
	private BuscaDaoSpring busca;
	private LogBuscaDao logBuscaDao;
	private PaginaDaoSpring paginaDao = null;
	private List<LogBusca> listLogBusca = new ArrayList<LogBusca>();
	private ItemConteudoDaoSpring itemConteudoDao;
	private List<PalavraChave> listPalavraChave = null;
	private Long nuPagina;
	private List<ListItem> listItemMenu = new ArrayList<ListItem>();
	/**
	 * PalavraChave do internauta
	 */
	private PalavraChave palavraChave = null;
	public PalavraChave getPalavraChave() {
		return palavraChave;
	}
	public void setPalavraChave(PalavraChave palavraChave) {
		this.palavraChave = palavraChave;
	}
	
	private Long nuItemMenuSecao = null;
	public Long getNuItemMenuSecao() {
		return nuItemMenuSecao;
	}
	public void setNuItemMenuSecao(Long nuItemMenuSecao) {
		this.nuItemMenuSecao = nuItemMenuSecao;
	}
	
	public BuscaAction(BuscaDaoSpring buscaDaoSpring, LogBuscaDao logBuscaDao,ItemConteudoDaoSpring itemConteudoDao,PaginaDaoSpring paginaDao) {
		busca = buscaDaoSpring;
		this.logBuscaDao = logBuscaDao;
		this.itemConteudoDao = itemConteudoDao;
		this.paginaDao = paginaDao;
	}

	/**
	 * Executa a busca avancada
	 * @return sucesso
	 */
	public String buscarAvancado() throws Exception{
		resultados = new ArrayList<ItemBusca>();
		if(txtBusca!=null && !txtBusca.equals("")){
			//faz a busca por setor
			List<ItemBusca> resultadosSujos = busca.listarAchados(txtBusca);
			for(ItemBusca itemBusca:resultadosSujos){
				//verificar se pertence ao setor
				Pagina pagina = paginaDao.select(itemBusca.getIdPagina());
				if(pagina.getItemMenuSecao().getNuItemMenu().equals(nuItemMenuSecao)){
					resultados.add(itemBusca);
				}
			}
			//logar a busca para gerar relatorios
			LogBusca logBusca = new LogBusca();
			logBusca.setDataHora(new Date());
			logBusca.setTxtBusca(txtBusca);
			logBuscaDao.create(logBusca);
		}else if(palavraChave!=null && palavraChave.getId()!=null){
			resultados = busca.buscarPorPalavraChave(palavraChave);
		}
		
		//abre a tela busca novamente
		return abrirBuscaAvancada();
	}
	
	/**
	 * Abre a tela de busca avancada do internauta
	 * @return sucesso
	 */
	public String abrirBuscaAvancada(){
		listPalavraChave = itemConteudoDao.listarPalavrasChave();
		if(nuPagina!=null){
			try {
				Pagina pagina = paginaDao.select(nuPagina);
				listItemMenu = PaginaAction.criarListaHierarquica(pagina.getSitio().getMenuPrincipal().getListItemMenu());
				if(nuItemMenuSecao==null){
					nuItemMenuSecao = pagina.getItemMenuSecao().getNuItemMenu();
				}
			} catch (Exception e) {
				logger.error("Erro ao abrir busca avancada ",e);
			}
		}
		return SUCCESS;
	}
	
	/**
	 * Busca do internauta
	 */
	public String execute() throws Exception {
		if(txtBusca==null || txtBusca.equals("")){
			resultados = new ArrayList<ItemBusca>();
		}else{
			resultados = busca.listarAchados(txtBusca);
			//logar a busca para gerar relatorios
			LogBusca logBusca = new LogBusca();
			logBusca.setDataHora(new Date());
			logBusca.setTxtBusca(txtBusca);
			logBuscaDao.create(logBusca);
		}
		
		
		//Contar
		List<LogBusca> listLogBusca = logBuscaDao.listarUltimas(300);
		HashMap<String,LogBusca> map = new HashMap<String,LogBusca>();
		
		for(LogBusca logBusca:listLogBusca){
			if(map.containsKey(logBusca.getTxtBusca())){
				LogBusca t = map.get(logBusca.getTxtBusca());
				t.maisMais();
			}else{
				logBusca.maisMais();
				map.put(logBusca.getTxtBusca(), logBusca);
			}
		}
		//gerar lista com unicos
		listLogBusca = new ArrayList<LogBusca>();
		Set<String> chaves = map.keySet();
		for(String key:chaves){
			listLogBusca.add(map.get(key));
		}
		//ordenar quantidade
		Collections.sort(listLogBusca,new Comparator<LogBusca>(){
			public int compare(LogBusca o1, LogBusca o2) {
				return o2.getContador()-o1.getContador();
			}
		});
		//pegar os X primeiros
		float total = 0;
		List<LogBusca> listLogBuscaXprimeiros = new ArrayList<LogBusca>();
		int xPrimeiros = Math.min(15,listLogBusca.size());
		for(int i=0;i<xPrimeiros;i++){
			LogBusca lb = listLogBusca.get(i);
			listLogBuscaXprimeiros.add(lb);
			total+=lb.getContador();
		}
		//ordenar nome;
		Collections.sort(listLogBuscaXprimeiros,new Comparator<LogBusca>(){
			public int compare(LogBusca o1, LogBusca o2) {
				return o1.getTxtBusca().compareTo(o2.getTxtBusca());
			}
		});
		
		//calcular o percentual de cada, e pegar o maior
		float maior = 0f;
		for(LogBusca lb:listLogBuscaXprimeiros){
			float perc = (float)(lb.getContador()/total) * 100;
			lb.setPercentual(perc);
			if(perc>maior) maior = perc;
		}
		//calcular o tamanho da fonte
		for(LogBusca lb:listLogBuscaXprimeiros){
			lb.setFontSize((int)(300 * lb.getPercentual()/maior) + 80);
		}
		
		//gerar o html do relatorio
		String relatorio="";
		
		for(int i=0;i<listLogBuscaXprimeiros.size();i++){
			LogBusca lb = listLogBuscaXprimeiros.get(i);
			if(i>0){
				relatorio+=", ";//Acessibilidade: separar todo link por um caractere imprimivel.
			}
			relatorio+="<span style=\"font-size: " + lb.getFontSize() + "%\" title=\"" + lb.getPercentual()+"%\" >"+
				"<a href=\"buscar.action?txtBusca=" + lb.getTxtBuscaUrlEncoded() + "\">" + lb.getTxtBusca().replace("<","&lt;") + "</a>" +
			"</span>";
		}
		RelatorioBusca rb = logBuscaDao.getRelatorioBusca();
		rb.setConteudo(relatorio);
		logBuscaDao.update(rb);
		
		this.listLogBusca = listLogBuscaXprimeiros;
		
		return SUCCESS;
	}
	
	/**
	 * Utilizado para o relatorio
	 * @return lista de LogBusca mais utilizados
	 */
	public List<LogBusca> getListLogBusca() {
		return listLogBusca;
	}
	
	public void setListLogBusca(List<LogBusca> listLogBusca) {
		this.listLogBusca = listLogBusca;
	}
	
	public void setTxtBusca(String txtBusca) {
		this.txtBusca = txtBusca;
	}
	
	public String getTxtBusca() {
		return txtBusca;
	}
	
	public String buscar() {
		resultados = busca.listarAchados(texto);
		return SUCCESS;
	}

	public String buscarAdministrativo() {
		resultados = busca.listarAchadosAdmin(texto);
		return SUCCESS;
	}

	public ArrayList<ItemBusca> getItensBusca() {
		return itensBusca;
	}

	public void setItensBusca(ArrayList<ItemBusca> itensBusca) {
		this.itensBusca = itensBusca;
	}

	public String getTexto() {
		return texto;
	}

	public void setTexto(String texto) {
		this.texto = texto;
	}

	public List<ItemBusca> getResultados() {
		return resultados;
	}

	public void setResultados(List<ItemBusca> resultados) {
		this.resultados = resultados;
	}
	
	public List<PalavraChave> getListPalavraChave() {
		return listPalavraChave;
	}
	public void setListPalavraChave(List<PalavraChave> listPalavraChave) {
		this.listPalavraChave = listPalavraChave;
	}
	
	public void setNuPagina(Long nu_pagina){
		this.nuPagina = nu_pagina;
	}
	
	public Long getNuPagina() {
		return nuPagina;
	}
	
	public List<ListItem> getListItemMenu() {
		return listItemMenu;
	}
	
	public void setListItemMenu(List<ListItem> listItemMenu) {
		this.listItemMenu = listItemMenu;
	}
}
